import { ETaskState } from "GameLoop/DecisionMaking/TaskDeclare/type";
import { ATaskAdapter } from ".";
import { generateUniqueId } from "utils/utils";
import { TeamUpgrader } from "GameLoop/WorldState/EntityManager/Entitys";
import { ATeamEntity } from "GameLoop/WorldState/EntityManager/Entitys/team";
import { TeamTaskChecker } from "../TaskCheck/TeamTaskChecker";
import { TaskHelper } from "utils/task/TaskHelper";
import { StationNetwork } from "GameLoop/Path/StationNetwork";
import { combatRoles } from "utils/constants/bodyconstant";

export class TeamTaskAdapter extends ATaskAdapter<"team">
{
    constructor(context:IContextGetter,world:WorldGetter)
    {
        super(context,world);
        TeamTaskChecker.notify = this.notify;
    }
    public bindTasks(room: Room, teamtasks:ITaskDeclare["team"][],customCheck:IConditionFunction): void 
    {
        const creepRecord = room.getIdleCreeps();
        for(const task of teamtasks)
        {
            const taskcreeps = task.data.creeps;
            for(let i=0;i<taskcreeps.length;i++)
            {
                let name  =   taskcreeps[i];
                if(!Game.creeps[name]  )
                {
                    task.data.creeps.splice(i,1);
                }
                else 
                {
                    i++;
                } 
            }
            const code = customCheck(room as Required<Room>,task)
            if(code == ETaskState.Complete  )
            {
                room.deleteTaskById(task.id,"team");
                continue;
            }else if(code == ETaskState.Pause)
            {
                taskcreeps.forEach(e=>Game.creeps[e].memory.taskid=undefined);
                task.data.creeps=[];
                /**
                 * @todo
                 * 怎样对小队解绑
                 * */ 
                continue;
            }
            if(ETaskState.Complete == this.checkState(room,task))
            {
                 
                room.deleteTaskById(task.id,"team");
                continue;
            }
            if(!task.data.cost  )
            {
                task.data.cost = TaskHelper.getTaskPathCost(room.name,task.data.room)
            }
            // 小队两种孵化模式。
            /**
             * a.对于分散得爬。孵化就能工作的。不等等待一起孵化
             * b.对于需要组合在一起工作的  就要等待一起孵化
             * 所以小队成员的孵化和绑定全部有小队自己解决
             * 
             * 另外任务类的孵化模式
            */
            // 对任务进行分类整理,先把爬和小队的孵化分开
            this.bindCreepToTask(room as Required< Room>,task,creepRecord);
            this.postSpawnTask(room as Required< Room>,task );
            this.bindTeam(room as Required< Room>,task,creepRecord);
            
        }
    }
    
    protected checkState(room:Room,task:ITaskDeclare["team"]):ETaskState
    {
        for(let k in task.data.teams)
        {
            for(const e of task.data.teams[k as EntityType])
            {
                const entity = room.getEntityByID(e);
                // entity?.updateMemory();
            }
        }

        return TeamTaskChecker.check(room,task);
    }
    
    /**
     * 创建小队绑定到任务
     * @param room 
     * @param task 
     * @param creep 
     */
    private bindTeam(room:Required< Room>,task:ITaskDeclare["team"],creep:Record<RoleName,Creep[]>)
    {
        for(const e of task.data.required)
        {
            
            let exist_team = task.data.teams[e[0].type];
            
            if(!exist_team)
            {
                exist_team=[];
                task.data.teams[e[0].type]=exist_team
            }
            let validTeam = 0;
            for(let i=0;i<exist_team.length;)
            {
                const team = exist_team[i];
                const curteam = this.world.EntityDB.getEntityByID<ATeamEntity>(team);
                if(curteam)
                {
                    this.bindCreepToTeam(room,curteam,creep,task);
                    if(curteam.entityType() == "TeamUpgrader")
                    {
                        curteam.postSpawn(task.priority);
                    }
                    const ttl = curteam.teamTimeTickLive;
                    if( ttl>task.data.cost)
                    {
                        validTeam++
                    }
                    i++;
                }
                else
                {
                   
                    if(room.memory.Nodes[team])
                    {
                        room.log("error",`team ${team} 实体不存在`,`但是内存存在`,`小队实体存在初始化错误!`);
                        exist_team.splice(i,1);
                    }
                    else 
                    {
                        room.log("warn",`team ${team} 不存在`,`删除小队`);
                        exist_team.splice(i,1);
                    }
                    
                }
            }
            const teams = room.getEntitys<"Team2">(e[0].type as any).filter(e=>e.getNodeMemory().bindTask == undefined);
            for(let i=0;i<teams.length&& validTeam<e[1];i++)
            {
                // 绑定空闲的小队
                teams[i].getNodeMemory().bindTask = task.id;
                exist_team.push(teams[i].GUID());
                validTeam++;
            }
            for(let i=validTeam;i<e[1];i++)
            {
                
                const guid = generateUniqueId();

                const team = this.world.EntityManager.addEntity<ITeamInitializer>(e[0].type,{
                    GUID:guid,
                    key:guid,
                    roomName:room.name
                }) as ATeamEntity;
                // 小队只有在初始化的时候才发起一次孵化请求.?
                team.getNodeMemory().required = e[0].creep; // 设置爬的需求
                (team.getNodeMemory()).bindTask = task.id;
                team.postSpawn(task.priority);
                exist_team.push(team.GUID());
            }

            
        }
    }


    /**
     * 多退少补，绑定爬
     * @param task 
     * @param creep 
     */
    private bindCreepToTask(room:Required< Room>,task:ITaskDeclare["team"],creep:Record<RoleName,Creep[]>)
    {
        if(!task.data.creepRequired)
        {
            return 
        }
        const bindCreep=(task:ITaskDeclare["team"],creep:Creep)=>
        {
            task.data.creeps.push(creep.name);
            creep.memory.taskid = task.id;
            room.removeIdleCreep(creep);
            
        }
 
        const existvalidCreeps:Record<RoleName,Creep[]>= this.getValidCreeps(task);

        for(const req of task.data.creepRequired)
        {
            let sum = 0;
            sum+=existvalidCreeps[req[0].Role]?existvalidCreeps[req[0].Role].length:0;
            if(sum< req[1])
            {
                // 不足
                let i=sum
                for( ;i<req[1];i++)
                {
                    if(creep[req[0].Role]?.length )
                    {
                        bindCreep(task,creep[req[0].Role].pop() as Creep);
                        
                        break;
                    }
                }
            }
            
        }

    }
  
    // 分配爬给小队
    /**
     * 
     * @param room 
     * @param team 
     * @param creeps 
     */
    private bindCreepToTeam(room:Required< Room>,team:ATeamEntity,creeps:Record<RoleName,Creep[]>,task:ITaskDeclare["team"])
    {
        // 绑定爬之前。先检测更新状态

        if(!team)
        {
            throw new Error(`team 未定义`);
        }
        const bindCreep=(team:ATeamEntity,creep:Creep)=>
        {
            if(combatRoles.has(creep.ActiveRole()))
            {   
                // 战斗爬
                if(creep.memory.teamid &&creep.memory.teamid == team.GUID())
                {
                    if(team.addCreep([creep]))
                    {
                        // creep.memory.taskid = task.id;
                        room.removeIdleCreep(creep);
                    }
                }
            }
            else
            {
                // 非战斗爬
                if(team.addCreep([creep]))
                {
                    // creep.memory.taskid = task.id;
                    room.removeIdleCreep(creep);
                }
            }
        }
        const existvalidCreeps:Record<RoleName,Creep[]>= team.groupCreeps;
        const memory = team.getNodeMemory();
        for(const req of memory.required)
        {
            const r = req[0].Role;
            let sum = existvalidCreeps[r]?existvalidCreeps[r].length:0;
            for(let i= sum;i<req[1];i++)
            {
                if(creeps[r]?.length)
                {
                    bindCreep(team,creeps[r].pop() as Creep);
                    break;
                }
            }
        }
    }
 // 检测
    /**
     *  投递任务绑定的单爬的孵化
     * @param room 
     * @param task 
     * @param role 
     * @param creepLimit role的数量限制
     * @param needcount 需要的数量, required 减去已经有的
     */
    private postSpawnTask(room:Required< Room>,task:ITaskDeclare["team"] )
    {
         
        const validcreeps = this.getValidCreeps(task);
        const spawnentity = room.getEntity("SpawnEntity");
        const existTask = spawnentity.getTasksByOwner(task.id);
        if(existTask)
        {
            return 
        }
        // const spawnRecord:Record<RoleName,[number,IBodyConfig]>={} as any;
        const spawntask = TaskHelper.getSpawnTask(task.id,undefined,  task.priority);
        for(const e of task.data.creepRequired)
        {
            const role =  e[0].Role;
            const existnum = validcreeps[role]?validcreeps[role].length:0;
            // 本任务已经达标了
            const spawnNum = spawnentity.getSpawnCountByRole(role,task.id)
           
            const tasklimit = e[1]- (spawnNum+existnum);
           
            if(tasklimit<=0)
            {
                // 正在孵化的。已经有的。达到了需求
                continue;
            }
            
            // spawnRecord[role] = [tasklimit, e[0]];
            TaskHelper.pushSpawnInfo(spawntask,e[0],tasklimit);
        }
        if(spawntask.data.spawn_info.length>0)
        {
            spawnentity.addTask(spawntask);
        }
       
    }

    private getValidCreeps(task:ITaskDeclare["team"])
    {
        const existvalidCreeps:Record<RoleName,Creep[]>={} as any;
        for(const e of task.data.creeps)
        {
            const creep = Game.creeps[e];
            if(!creep || (creep && creep.ticksToLive && creep.ticksToLive<task.data.cost))
            {
                continue;
            }
            if(existvalidCreeps[creep.memory.Role])
            {
                existvalidCreeps[creep.memory.Role].push(creep)
            }
            else
            {
                existvalidCreeps[creep.memory.Role]= [creep]
            }
            
        }
        return existvalidCreeps
    }
    
    //
    // private getSpawnRoleConfig(role:RoleName,room:Required<Room>,task:ITaskDeclare["creep"])
    // {
    //     if(task.data.bodyconfig)
    //     {
    //         const bodyconfig = task.data.bodyconfig.find(e=>e.Role ==role);
    //         if(bodyconfig)
    //         {
    //             return bodyconfig
    //         }
    //     }
    //     return getRoleConfig(role,room.controller.level);
    // }
}